package com.itesm.distribuidos.tarea4;

import java.util.Random;

public class MatrixOperations {
	
	/**
	 * Crea una matriz cuadrada aleatoriamente con enteros entre 1 y 100
	 * @param size	El tamaño de la matriz a generar
	 * @return 	La matriz de Strings 
	 */
	public String[][] createRandomStringMatrix(int size)
	{
		String[][] matrix = new String[size][size];
		Random r = new Random();
		
		for(int i=0; i<size;i++)
			for(int j=0;j<size;j++)
				matrix[i][j] = Integer.toString(r.nextInt(100)+1);
		
		return matrix;
	}
	
	/**
	 * Realiza la suma de matrices
	 * @param a		Matriz operando 1
	 * @param b		Matriz operando 2
	 * @return		El resultado de la suma de a + b
	 */
	public String[][] addition(String[][] a, String[][] b)
	{
		String[][] matrix = new String[a.length][a.length];
		
		for(int i=0; i<a.length; i++)
            for(int j=0; j<a.length; j++)
            {
            	int result = (Integer.parseInt(a[i][j])+Integer.parseInt(b[i][j]));
                matrix[i][j]= Integer.toString(result);
            }
		
		return matrix;
	}
	
	/**
	 * Realiza la resta de matrices
	 * @param a		Matriz operando 1
	 * @param b		Matriz operando 2
	 * @return		El resultado de la resta de a - b
	 */
	public String[][] substraction(String[][] a, String[][] b)
	{
		String[][] matrix = new String[a.length][a.length];
		
		for(int i=0; i<a.length; i++)
            for(int j=0; j<a.length; j++)
            {
            	int result = (Integer.parseInt(a[i][j])-Integer.parseInt(b[i][j]));
                matrix[i][j]= Integer.toString(result);
            }
		
		return matrix;
	}
	
	/**
	 * Multiplica dos matrices
	 * @param a		Matriz operando 1
	 * @param b		Matriz operando 2	
	 * @return		La multiplicación de a * b
	 */
	public String[][] multiplication(String[][] a, String[][] b)
	{
		String[][] matrix = new String[a.length][a.length];
		int aux; 
		
		for(int i=0; i<a.length; i++)
	        for(int j=0; j<a.length; j++)
	        {
	        	aux = 0;
	            for(int k=0; k<a.length; k++){
	            	aux += Integer.parseInt(a[i][k])*Integer.parseInt(b[k][j]);
	            }
	            matrix[i][j] = Integer.toString(aux); 
	        }
	                
		
		return matrix;
	}
	
	/**
	 * Realiza la división de matrices. En realidad la división de matrices como tal no existe
	 * pero puede decirse que si multiplicas la matriz A por la inversa de B, se obtiene la división 
	 * de A / B.
	 * 
	 * NO TODAS LAS MATRICES TIENEN INVERSA, entonces estamos calculando la división como en una suma o resta
	 * 
	 * @param a		Matriz de divisores
	 * @param b		Matriz de dividendos
	 * @return		El resultado de la división
	 */
	public String[][] division(String[][] a, String[][] b)
	{
		//La verdarero algoritmo de división en las dos siguientes lineas
		//double[][] c = this.inversa(b);	
		//return this.multiplication(a, c);
		
		String[][] matrix = new String[a.length][a.length];
		
		for(int i=0; i<a.length; i++)
		{
            for(int j=0; j<a.length; j++)
            {
            	double res = (double)Integer.parseInt(a[i][j]) / Integer.parseInt(b[i][j]);
                matrix[i][j]=Double.toString(res);
            }
		}
		
		return matrix;
	}
	
	/**
	 * Imprime en consola la matriz dada
	 * @param a
	 */
	public void printMatrix(String[][] a)
	{
		for(int i=0; i<a.length; i++)
		{
            for(int j=0; j<a.length; j++)
            {
                System.out.print(a[i][j] + "\n");
            }
            System.out.println();
		}
	}
	
	/**
	 * Calcula la inversa de una matriz (Si no tiene entonces tendremos una matriz con 0s)
	 * 
	 * @param d		La matriz para calcular su inversa		
	 * @return		La inversa de la matriz
	 */
	public double[][] inversa(int[][] d){
		int n = d.length;
				
        int[][] a= d;
        int[][] b= new int[n][n];
        double[][] c= new double[n][n];
        
        for(int i=0; i<n; i++){
            b[i][i]=1;
        }
        
        for(int k=0; k<n-1; k++)
        {
            for(int i=k+1; i<n; i++)
            {
                for(int s=0; s<n; s++)
                    b[i][s]-=a[i][k]*b[k][s]/a[k][k];
                
                for(int j=k+1; j<n; j++)
                    a[i][j]-=a[i][k]*a[k][j]/a[k][k];
            }
        }

        for(int s=0; s<n; s++)
        {
            c[n-1][s]=b[n-1][s]/a[n-1][n-1];
            
            for(int i=n-2; i>=0; i--)
            {
                c[i][s]=b[i][s]/a[i][i];
                
                for(int k=n-1; k>i; k--)
                    c[i][s]-=a[i][k]*c[k][s]/a[i][i];
            }
        }
        return c;
    }
	
	public static void main(String...arg)
	{
		//nada mas para probar
		MatrixOperations operations = new MatrixOperations();
		String[][] matrix;
		
		String[][] a = operations.createRandomStringMatrix(4);
		String[][] b = operations.createRandomStringMatrix(4);
		
		operations.printMatrix(a);
		System.out.println("----------------");
		operations.printMatrix(b);
		System.out.println("----------------");
		
		matrix = operations.addition(a, b);
		operations.printMatrix(matrix);

	}
}
